package com.robusta.cityuate.services;

import java.util.ArrayList;
import com.robusta.cityuate.R;

import com.robusta.cityuate.activities.RemindersListActivity;


import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;


import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;

import android.widget.Toast;
// this class is a background service that get check the location related to remionders.
public class LocationService extends Service {
	private NotificationManager mNM;
	private int NOTIFICATION = R.string.notification_found;
	//private Geocoder gc;
	private LocationManager locationManager;
	private Location destinationLocation;
	private ArrayList<ArrayList<String>> reminders;
	private ArrayList<String> closestReminder;
	private double distance;
	private GeoUpdateHandler locationlistener;
	private Thread task;

	/**
	 * Class for clients to access. Because we know this service always runs in
	 * the same process as its clients, we don't need to deal with IPC.
	 */
	public class LocalBinder extends Binder {
		LocationService getService() {
			return LocationService.this;
		}
	}

	@Override
	public void onCreate() {
		mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		task = new Thread() {
			public void run() {
				Looper.prepare();
				reminders = getAllReminders();
				if(reminders.size()==0){
					stopSelf();
				}else{
				locationlistener = new GeoUpdateHandler();
				locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
				locationManager.requestLocationUpdates(
						LocationManager.NETWORK_PROVIDER, 0, 0,
						locationlistener);
				destinationLocation = new Location(
						LocationManager.NETWORK_PROVIDER);
				distance = Double.MIN_VALUE;
				// Log.i("LocalService", "Received start id " + startId + ": " +
				// intent);
				getClosestDestination();
				destinationLocation.setLongitude(Double
						.parseDouble(closestReminder.get(2)));
				destinationLocation.setLatitude(Double
						.parseDouble(closestReminder.get(3)));
				System.out.println("lol");
				}
				Looper.loop();
			}
		};
		task.start();
	}

	public class GeoUpdateHandler implements LocationListener {

		@Override
		public void onLocationChanged(android.location.Location arg0) {
			System.out.println(distance);
			System.out.println(arg0.getProvider());
			if (distance > 5000) {
				locationManager.removeUpdates(this);
				locationlistener = new GeoUpdateHandler();
				locationManager.requestLocationUpdates(
						LocationManager.NETWORK_PROVIDER, 0, 0,locationlistener);
				distance = locationManager.getLastKnownLocation(
						LocationManager.NETWORK_PROVIDER).distanceTo(
						destinationLocation);
			} else {
				locationManager.removeUpdates(this);
				locationlistener = new GeoUpdateHandler();
				locationManager.requestLocationUpdates(
						LocationManager.GPS_PROVIDER, 0, 0,
						locationlistener);
				distance = locationManager
						.getLastKnownLocation(LocationManager.GPS_PROVIDER) == null ? locationManager
						.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
						.distanceTo(destinationLocation) : locationManager
						.getLastKnownLocation(LocationManager.GPS_PROVIDER)
						.distanceTo(destinationLocation);
				if (distance <= 50) {
					showGPSNotification();
				}
			}
			// need to be revised for quality issues
			getClosestDestination();
			if(reminders.size() !=0){
			destinationLocation.setLongitude(Double.parseDouble(closestReminder
					.get(2)));
			destinationLocation.setLatitude(Double.parseDouble(closestReminder
					.get(3)));
			}
		}

		@Override
		public void onProviderDisabled(java.lang.String arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onProviderEnabled(java.lang.String arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onStatusChanged(java.lang.String arg0, int arg1, Bundle arg2) {
			// TODO Auto-generated method stub

		}

	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		
		return START_STICKY;
	}
//getting the closest reminder from my current location get checked each location update.
	private void getClosestDestination() {
		reminders = getAllReminders();
		double minDistance = Double.MAX_VALUE;
		for (int i = 0; i < reminders.size(); i++) {
			//double lo = Double.parseDouble(reminders.get(i).get(2));
			double la = Double.parseDouble(reminders.get(i).get(3));
			Location temp = new Location(LocationManager.NETWORK_PROVIDER);
			temp.setLongitude(la);
			temp.setLatitude(la);
			double distance = locationManager.getLastKnownLocation(
					LocationManager.NETWORK_PROVIDER).distanceTo(temp);
			if (distance < minDistance) {
				minDistance = distance;
				closestReminder = reminders.get(i);
			}
		}
		if (reminders.size() == 0) {
			this.stopSelf();
			locationManager.removeUpdates(locationlistener);
		}
	}

	private ArrayList<ArrayList<String>> getAllReminders() {
		return DBClass.getTable(this, DBClass.TABLE_NAME_REMINDER);
	}

	@Override
	public void onDestroy() {
		//mNM.cancel(NOTIFICATION);
		Toast.makeText(this, "Reminder Stopped", Toast.LENGTH_LONG).show();
	}

	// This is the object that receives interactions from clients. See
	// RemoteService for a more complete example.
	private final IBinder mBinder = new LocalBinder();

	/**
	 * Show a notification while this service is running.
	 */

	private void showGPSNotification() {
		// In this sample, we'll use the same text for the ticker and the
		// expanded notification
		if (closestReminder != null) {
			CharSequence text = closestReminder.get(4);
			// Set the icon, scrolling text and timestamp
			Notification notification = new Notification(
					android.R.drawable.stat_notify_more, text, 
					System.currentTimeMillis());
			notification.flags = Notification.FLAG_SHOW_LIGHTS;
			// The PendingIntent to launch our activity if the user selects this
			// notification
			Intent i = new Intent(this, RemindersListActivity.class);
			PendingIntent contentIntent = PendingIntent.getActivity(this, 0, i,
					PendingIntent.FLAG_UPDATE_CURRENT);

			// Set the info for the views that show in the notification panel.
			notification.setLatestEventInfo(this, "Location Tracker", text,
					contentIntent);

			// Send the notification.
			mNM.notify(NOTIFICATION, notification);
			deleteFromDB(closestReminder.get(0));
			closestReminder = null;
			getClosestDestination();
			if(reminders.size()!=0){
			destinationLocation.setLongitude(Double.parseDouble(closestReminder
					.get(2)));
			destinationLocation.setLatitude(Double.parseDouble(closestReminder
					.get(3)));
			}
		}

	}

	public void deleteFromDB(String id) {
		DBClass.DeleteFromTable(this, DBClass.TABLE_NAME_REMINDER, id);
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
}